pub mod event_t {
    use web_sys::HtmlInputElement;
    use yew::{html, Component, Context, Html, NodeRef};

    pub enum OtsMsg {
        InputChange,
    }
    pub struct OtsNodeRefComp {
        my_input: NodeRef,
    }

    impl Component for OtsNodeRefComp {
        type Message = OtsMsg;
        type Properties = ();

        fn create(_ctx: &Context<Self>) -> Self {
            Self { my_input: NodeRef::default() }
        }

        fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
            match msg {
                OtsMsg::InputChange => {
                    if let Some(input) = self.my_input.cast::<HtmlInputElement>() {
                        let value = input.value();
                        weblog::console_log!(value);
                    }
                    true
                }
                _ => {
                    false
                }
            }
        }

        fn view(&self, ctx: &Context<Self>) -> Html {
            let link = ctx.link();
            let onchange = link.callback(|_| OtsMsg::InputChange);
            html!{
                <div>
                    <label for="ots-NodeRef-Input">
                        {"Ots-NodeRef-Input"}
                    </label>
                    <input
                        ref={self.my_input.clone()}
                        {onchange}
                        type="text"
                        id="ots-NodeRef-Input"
                    />
                </div>
            }
        }
    }

    pub struct NodeRefComp {
        my_input: NodeRef,
    }

    pub enum Msg {
        InputValue(String),
    }

    impl Component for NodeRefComp {
        type Message = Msg; 

        type Properties = ();

        fn create(_ctx: &Context<Self>) -> Self {
            Self { 
                my_input: NodeRef::default(),
            }
        }
        fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
            match msg {
                Msg::InputValue(value) => {
                    weblog::console_log!(value);
                    true
                }
            }
        }

        fn view(&self, ctx: &Context<Self>) -> Html {
            // ignore the event use NodeRef::Cast to get a Option<HtmlInputElement>
            let link = ctx.link();
            let my_input_ref = self.my_input.clone();
            let onchange = link.batch_callback(move |_| {
                let input = my_input_ref.cast::<HtmlInputElement>();
                input.map(|input| Msg::InputValue(input.value()))
            });
            html!{
                <div>
                    <label for="NodeRef-input">
                        {"NodeRef input"}
                    </label>
                    <input 
                        ref={self.my_input.clone()}
                        type="text"
                        id="input"
                        {onchange}
                    />
                </div>
            }
        }
    }
}